import { BaseService, CoolCommException } from "@cool-midway/core";
import { InjectEntityModel } from "@midwayjs/typeorm";
import { Equal, In, Repository } from "typeorm";
import { CommentInfoEntity, RelatedType } from "../entity/info";
import { Inject, Provide } from "@midwayjs/core";
import { Context } from "@midwayjs/koa";
import { AddCommentDTO, UserCommentPageDTO } from "../dto/info";
import { ProductInfoEntity } from "../../product/entity/info";
import { OrderInfoEntity } from "../../order/entity/info";
import { ProviderProfileEntity } from "../../provider/entity/profile";
import { ProviderTeamEntity } from "../../provider/entity/team";
import { CarInfoEntity } from "../../transport/entity/car/info";
import { TransportScheduleEntity } from "../../transport/entity/schedule";
import { CommentInviteEntity } from "../entity/invite";
import { UserInfoEntity } from "../../user/entity/info";

@Provide()
export class CommentInfoService extends BaseService {
    @InjectEntityModel(CommentInfoEntity)
    commentInfoModel: Repository<CommentInfoEntity>

    @InjectEntityModel(ProductInfoEntity)
    productInfoModel: Repository<ProductInfoEntity>

    @InjectEntityModel(OrderInfoEntity)
    orderInfoModel: Repository<OrderInfoEntity>

    @InjectEntityModel(ProviderProfileEntity)
    providerProfileModel: Repository<ProviderProfileEntity>

    @InjectEntityModel(ProviderTeamEntity)
    providerTeamModel: Repository<ProviderTeamEntity>

    @InjectEntityModel(CarInfoEntity)
    carInfoModel: Repository<CarInfoEntity>

    @InjectEntityModel(TransportScheduleEntity)
    scheduleModel: Repository<TransportScheduleEntity>

    @InjectEntityModel(CommentInviteEntity)
    commentInviteModel: Repository<CommentInviteEntity>

    @InjectEntityModel(UserInfoEntity)
    userInfoModel: Repository<UserInfoEntity>

    @Inject()
    ctx: Context

    /**
     * 查询评论列表
     * @param relatedId 
     * @param relatedType 
     */
    async list(relatedId: number, relatedType: RelatedType) {
        const queryBuilder = this.commentInfoModel.createQueryBuilder('comment');
        queryBuilder.where('comment.relatedId = :relatedId', { relatedId });
        queryBuilder.andWhere('comment.relatedType = :relatedType', { relatedType });
        queryBuilder.orderBy('comment.createTime', 'DESC');
        const list = await queryBuilder.getMany();
        return list;
    }


    /**
     * 用户端新增评论
     * @param param
     * @returns
     */
    async add(dto: AddCommentDTO) {
        const { relatedId, relatedType, content, images, scoreList } = dto;
        const userId = this.ctx.user?.id;
        if (!userId) {
            throw new CoolCommException('请先登录后再评价');
        }
        const normalizedScoreList = scoreList?.length ? scoreList : [];
        const normalizedImages = images?.length ? images : [];
        const averageScore = this.calcAverageScore(normalizedScoreList);
        return await this.commentInfoModel.save({
            content,
            images: normalizedImages,
            scoreList: normalizedScoreList,
            userId,
            relatedId,
            relatedType,
            averageScore,
        });
    }

    /**
     * 计算平均分
     * @param scores 
     * @returns 
     */
    private calcAverageScore(scores: { score: number }[] = []) {
        if (!scores.length) {
            return 0;
        }
        const total = scores.reduce((sum, item) => {
            const currentScore = Number(item?.score || 0);
            return sum + currentScore;
        }, 0);
        return Number((total / scores.length).toFixed(1));
    }

    /**
     * 我的评论列表
     * @param dto
     */
    async myComments(dto: UserCommentPageDTO) {
        const userId = this.ctx.user?.id;
        if (!userId) {
            throw new CoolCommException('请先登录后再查看评论');
        }
        const page = dto?.page ?? 1;
        const size = dto?.size ?? 10;
        const queryBuilder = this.commentInfoModel.createQueryBuilder('comment');
        queryBuilder.where('comment.userId = :userId', { userId });
        queryBuilder.orderBy('comment.createTime', 'DESC');
        const [list, total] = await queryBuilder
            .skip((page - 1) * size)
            .take(size)
            .getManyAndCount();
        const enrichedList = await this.attachCommentDetails(list);
        return {
            list: enrichedList,
            pagination: {
                page,
                size,
                total,
            },
        };
    }

    /**
     * 根据关联信息获取实体详情
     * @param relatedType 
     * @param relatedId 
     */
    async getRelatedEntity(relatedType: RelatedType, relatedId: number) {
        if (!relatedId || !relatedType) {
            throw new CoolCommException('关联信息不完整');
        }
        switch (relatedType) {
            case RelatedType.PRODUCT:
                return await this.productInfoModel.findOne({ where: { id: Equal(relatedId) } });
            case RelatedType.ORDER:
                return await this.orderInfoModel.findOne({ where: { id: Equal(relatedId) } });
            case RelatedType.PROVIDER:
                return await this.providerProfileModel.findOne({ where: { providerId: Equal(relatedId) } });
            case RelatedType.TEAM:
                return await this.providerTeamModel.findOne({ where: { id: Equal(relatedId) } });
            case RelatedType.CAR:
                return await this.carInfoModel.findOne({ where: { id: Equal(relatedId) } });
            case RelatedType.SCHEDULE:
                return await this.scheduleModel.findOne({ where: { id: Equal(relatedId) } });
            case RelatedType.INVITE:
                return await this.commentInviteModel.findOne({ where: { id: Equal(relatedId) } });
            default:
                return null;
        }
    }

    /**
     * 补充评论关联实体与用户信息
     * @param comments 
     */
    private async attachCommentDetails(comments: CommentInfoEntity[]) {
        if (!comments?.length) {
            return [];
        }
        const userIds = Array.from(new Set(comments.map(item => item.userId).filter(Boolean)));
        const users = userIds.length
            ? await this.userInfoModel.find({
                where: { id: In(userIds) },
            })
            : [];
        const userMap = new Map(users.map(user => [user.id, user]));

        return await Promise.all(
            comments.map(async comment => {
                const user = userMap.get(comment.userId) || null;
                const relatedEntity = await this.getRelatedEntity(comment.relatedType, comment.relatedId);
                return {
                    ...comment,
                    user,
                    relatedEntity,
                };
            })
        );
    }
}